package cn.ycc1.baseset.classes;

/**
 * 嵌套类
 * @author ycc
 * @date 2025/3/4
 * The Java programming language allows you to define a class within another class.
 * Such a class is called a nested class and is illustrated here:
 *
 * class OuterClass {
 *     ...
 *     class NestedClass {
 *         ...
 *     }
 * }
 * Terminology: Nested classes are divided into two categories: non-static and static.
 * Non-static nested classes are called inner classes.
 * Nested classes that are declared static are called static nested classes.
 *
 * class OuterClass {
 *     ...
 *     class InnerClass {
 *         ...
 *     }
 *     static class StaticNestedClass {
 *         ...
 *     }
 * }
 * A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have
 * access to other members of the enclosing class, even if they are declared private.
 * Static nested classes do not have access to other members of the enclosing class.
 * As a member of the OuterClass, a nested class can be declared private, public, protected,
 * or package private. Recall that outer classes can only be declared public or package private.
 *
 * Why Use Nested Classes?
 * Compelling reasons for using nested classes include the following:
 *
 * It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class,
 * then it is logical to embed it in that class and keep the two together.
 * Nesting such "helper classes" makes their package more streamlined.
 * It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of
 * A that would otherwise be declared private. By hiding class B within class A, A's members can be declared
 * private and B can access them. In addition, B itself can be hidden from the outside world.
 * It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the
 * code closer to where it is used.
 *
 * To instantiate an inner class, you must first instantiate the outer class.
 * Then, create the inner object within the outer object with this syntax:
 *
 * OuterClass outerObject = new OuterClass();
 * OuterClass.InnerClass innerObject = outerObject.new InnerClass();
 * There are two special kinds of inner classes: local classes and anonymous classes.
 *
 * You instantiate a static nested class the same way as a top-level class:
 *
 * StaticNestedClass staticNestedObject = new StaticNestedClass();
 *
 *
 */
public class NestedClasses {
    public int x = 0;

    class FirstLevel {

        public int x = 1;

        void methodInFirstLevel(int x) {
            System.out.println("x = " + x);
            System.out.println("this.x = " + this.x);
            System.out.println("ShadowTest.this.x = " + NestedClasses.this.x);
        }
    }

    public static void main(String... args) {
        NestedClasses st = new NestedClasses();
        NestedClasses.FirstLevel fl = st.new FirstLevel();
        fl.methodInFirstLevel(23);
    }

    public class DataStructure {

        // Create an array
        private final static int SIZE = 15;
        private int[] arrayOfInts = new int[SIZE];

        public DataStructure() {
            // fill the array with ascending integer values
            for (int i = 0; i < SIZE; i++) {
                arrayOfInts[i] = i;
            }
        }

        public void printEven() {

            // Print out values of even indices of the array
            DataStructureIterator iterator = this.new EvenIterator();
            while (iterator.hasNext()) {
                System.out.print(iterator.next() + " ");
            }
            System.out.println();
        }

        interface DataStructureIterator extends java.util.Iterator<Integer> { }

        // Inner class implements the DataStructureIterator interface,
        // which extends the Iterator<Integer> interface

        private class EvenIterator implements DataStructureIterator {

            // Start stepping through the array from the beginning
            private int nextIndex = 0;

            public boolean hasNext() {

                // Check if the current element is the last in the array
                return (nextIndex <= SIZE - 1);
            }

            public Integer next() {

                // Record a value of an even index of the array
                Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);

                // Get the next even element
                nextIndex += 2;
                return retValue;
            }
        }

        public void main(String s[]) {

            // Fill the array with integer values and print out only
            // values of even indices
            DataStructure ds = new DataStructure();
            ds.printEven();
        }
    }

    /**
     * Anonymous Classes 匿名类
     * Anonymous classes enable you to make your code more concise.
     * They enable you to declare and instantiate a class at the same time.
     * They are like local classes except that they do not have a name.
     * Use them if you need to use a local class only once.
     */
    NestedClasses frenchGreeting = new NestedClasses() {
        String name = "tout le monde";
        public void greet() {
            greetSomeone("tout le monde");
        }
        public void greetSomeone(String someone) {
            name = someone;
            System.out.println("Salut " + name);
        }
    };

}




